package com.wlin.leaf.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.*;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;

/**
 * Copyright (c) 2010-3020 Zhongshan Pole 3D Electronic Tech. Co., Ltd. All Rights Reserved.
 * <p>
 * This software is the confidential and proprietary information of
 * Zhongshan Pole 3D Electronic Tech. You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the agreements
 * you entered into with Zhongshan Pole 3D Electronic Tech.
 * <p>
 * 项目名称：diyhome-parent
 * 类名称：IpPortUtils
 * 类描述： ${DESCRIPTION}
 *
 * @author wlin
 * @version 1.0
 * @since 2018/9/21
 */
public class IpPortUtils {

    private static Logger logger = LoggerFactory.getLogger(IpPortUtils.class);

    /**
     * 获得内网IP
     * @return
     * @throws UnknownHostException
     */
    public static String getHostAddress() throws UnknownHostException {
        Enumeration<NetworkInterface> netInterfaces;
        try {
            netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
                Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    InetAddress ip = ips.nextElement();
                    if (ip.isSiteLocalAddress()) {
                        return ip.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return InetAddress.getLocalHost().getHostAddress();
    }

    /***
     * 获取本机启动端口号,目前只测试过支持tomcat
     * @return
     */
    public static Integer getNonSecurePort() throws MalformedObjectNameException {
        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
        if(objectNames == null || objectNames.isEmpty() ){ //适配 tomcat8.0.36
            objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                    Query.match(Query.attr("protocol"), Query.value("org.apache.coyote.http11.Http11Nio2Protocol")));
        }
        if(objectNames == null || objectNames.isEmpty()){
            throw new IllegalArgumentException("无法正确获取端口号");
        }
        Integer port = Integer.valueOf(objectNames.iterator().next().getKeyProperty("port"));
        return port;
    }

    /**
     * 获取服务端口号
     * @return 端口号
     * @throws ReflectionException
     * @throws MBeanException
     * @throws InstanceNotFoundException
     * @throws AttributeNotFoundException
     */
    public static ServerInfo getServerInfo(boolean http) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, MalformedObjectNameException, UnknownHostException {
        MBeanServer mBeanServer = null;
        if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
            mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
        }

        if (mBeanServer == null) {
            logger.debug("调用findMBeanServer查询到的结果为null");
            throw new IllegalStateException("无法获取信息");
        }

        Set<ObjectName> names = null;
        names = mBeanServer.queryNames(new ObjectName("*:type=Connector,*"), null);

        Iterator<ObjectName> it = names.iterator();
        ObjectName objName = null;
        while (it.hasNext()) {
            objName = it.next();
            String protocol = (String)mBeanServer.getAttribute(objName, "protocol");
            String scheme = (String)mBeanServer.getAttribute(objName, "scheme");
            Boolean secureValue = (Boolean)mBeanServer.getAttribute(objName, "secure");
            Boolean SSLEnabled = (Boolean)mBeanServer.getAttribute(objName, "SSLEnabled");
            if (SSLEnabled != null && SSLEnabled) {// tomcat6开始用SSLEnabled
                secureValue = true;// SSLEnabled=true但secure未配置的情况
                scheme = "https";
            }
            if (http && protocol != null && (!"HTTP/1.1".equals(protocol) || !protocol.contains("http"))) {
                continue;
            }
            //if (secure && "https".equals(scheme) && secureValue) {
            //    Integer port =  Integer.valueOf(mBeanServer.getAttribute(objName, "port");
            //} else if (!secure && !"https".equals(scheme) && !secureValue) {
            //    Integer port =  Integer.valueOf(mBeanServer.getAttribute(objName, "port");
            //}
            Integer port =  (Integer)mBeanServer.getAttribute(objName, "port");
            return new ServerInfo(getHostAddress(),port,protocol,scheme,secureValue,SSLEnabled);
        }
        throw new IllegalStateException("无法获取信息");
    }

    public static class ServerInfo{
        private String host;
        private Integer port;
        private String protocol;
        private String scheme;
        private Boolean secureValue;
        private Boolean SSLEnabled;

        public ServerInfo(String host, Integer port, String protocol, String scheme, Boolean secureValue, Boolean SSLEnabled) {
            this.host = host;
            this.port = port;
            this.protocol = protocol;
            this.scheme = scheme;
            this.secureValue = secureValue;
            this.SSLEnabled = SSLEnabled;
        }

        public String getHost() {
            return host;
        }

        public ServerInfo setHost(String host) {
            this.host = host;
            return this;
        }

        public Integer getPort() {
            return port;
        }

        public ServerInfo setPort(Integer port) {
            this.port = port;
            return this;
        }

        public String getProtocol() {
            return protocol;
        }

        public ServerInfo setProtocol(String protocol) {
            this.protocol = protocol;
            return this;
        }

        public String getScheme() {
            return scheme;
        }

        public ServerInfo setScheme(String scheme) {
            this.scheme = scheme;
            return this;
        }

        public Boolean getSecureValue() {
            return secureValue;
        }

        public ServerInfo setSecureValue(Boolean secureValue) {
            this.secureValue = secureValue;
            return this;
        }

        public Boolean getSSLEnabled() {
            return SSLEnabled;
        }

        public ServerInfo setSSLEnabled(Boolean SSLEnabled) {
            this.SSLEnabled = SSLEnabled;
            return this;
        }
    }
}
